package menu
{
	import com.*;
	import com.Logging.ClientAction;
	import com.Logging.ClientActionType;
	import data.*;
	import events.GCEvent;
	import ui.button.GCButton;
	import ui.GCBuildingButton;
	import ui.popup.GCTextPopup;
	import ui.textfield.GCStylizedText;
	import ui.textfield.GCTextField;
		
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.utils.Dictionary;
	
	/**
	 * ...
	 * @author Jason Won
	 */
	public class GCTradePostMenu extends Sprite implements GCSuperMenu
	{
		private static var BUILDING_BUTTON_OFFSET:int = 20;
		
		private var _menuLabel:Sprite;
		
		private var _buildButton:GCButton;
		private var _exitButton:GCButton;
		
		private var _descriptionArea:Sprite;
		private var _descriptionText:GCStylizedText;
		private var _costText:Sprite;
		
		private var _buildingsArea:Sprite;
		private var _totalBuildings:Vector.<GCBuildingButton>;
		
		/*
		 * Keep track of coordinates to properly place the
		 * building buttons.
		 */
		private var _buildButtonX:int;
		private var _buildButtonY:int;
		
		// What building has been focused on
		private var _targetedBuilding:GCBuildingButton;
		
		public function GCTradePostMenu() 
		{	
			// Background
			var background:Bitmap = GCResources.getResource("main_background");
			this.addChild(background);
				
			_menuLabel = new Sprite();
			_buildButton = new GCButton(onBuildClick);
			_exitButton = new GCButton(onExitPost);
			_descriptionArea = new Sprite();
			_descriptionText = new GCStylizedText();
			_buildingsArea = new Sprite();
			_costText = new Sprite();
			_totalBuildings = new Vector.<GCBuildingButton>();
			
			_targetedBuilding = null;
			
			init();
		}
		
		private function init():void
		{			
			_descriptionText.setBgStyle(GCStylizedText.STYLE_ONE, 200, 200);
			_descriptionText.y = 100;
			_descriptionArea.addChild(_descriptionText);
			_descriptionArea.graphics.beginFill(0x000000, 0);
			_descriptionArea.graphics.drawRect(0, 0, 200, this.height);
			_descriptionArea.graphics.endFill();
			_descriptionArea.x = this.width - _descriptionArea.width;
			_descriptionArea.y = 0;
			
			_buildButton.loadGraphic(GCResources.plate, 150, 30);
			_buildButton.loadText("Construct Building");
			_buildButton.x = _descriptionArea.x + _descriptionArea.width / 4;
			_buildButton.y = this.height - 100;
			
			var buildAreaLabel:GCStylizedText = new GCStylizedText();
			buildAreaLabel.text = "All buildings that can be constructed in this city! Click on one to view its information";
			buildAreaLabel.setBgStyle(GCStylizedText.STYLE_ONE, 500, 70);
			buildAreaLabel.y = - buildAreaLabel.height;
			_buildingsArea.addChild(buildAreaLabel);
			_buildingsArea.x = 100;
			_buildingsArea.y = 100;
			
			var costTextLabel:GCStylizedText = new GCStylizedText();
			costTextLabel.text = "Cost to construct:";
			costTextLabel.setBgStyle(GCStylizedText.STYLE_THREE, _descriptionArea.width, 200);
			_costText.addChild(costTextLabel);
			_costText.x = 0;
			_costText.y = this.height - 300;//_costText.height;
			
			_exitButton.loadGraphic(GCResources.plate, 100, 30);
			_exitButton.loadText("Exit Post");
			_exitButton.x = 400;
			_exitButton.y = 480;
			
			this.addChild(_menuLabel);
			this.addChild(_buildingsArea);
			this.addChild(_descriptionArea);
			this.addChild(_exitButton);
		}
				
		/**
		 * On open we will need to get a list of all possible buildings
		 * that can be constructed at this city. It will even include ones
		 * that the player has already built.
		 */
		public function openMenu(allBuildings:Vector.<uint>, alreadyBuilt:Vector.<uint>):void
		{
			_buildButtonX = 0;
			_buildButtonY = 0;
			
			_totalBuildings = new Vector.<GCBuildingButton>();
			
			/*
			 * Based on the buildings in the city, we will layout the available
			 * buildings that the user can construct.
			 */
			var buildingId:uint;
			for each (buildingId in allBuildings)
			{
				
				/*
				* Roy-- tutorial
				* 
				*/
				if (GCPlayState.tutorialSequence.currentTutorialStage == GCTutorial.STAGE_BUILD_GATHER)
				{
					if (buildingId != GCBuildingData.BUILDING_FARM &&
						buildingId != GCBuildingData.BUILDING_WAREHOUSE)
					{
						continue;
					}
				}
				
				
				var building:GCBuildingButton = new GCBuildingButton(buildingId, _buildButtonX, _buildButtonY);
				building.addEventListener(MouseEvent.CLICK, onButtonClicked);
				
				var index:int = alreadyBuilt.indexOf(buildingId)
				if (index != -1)
				{
					alreadyBuilt.splice(index, 1);
					building.setDisabled();
				}
				
				_buildingsArea.addChild(building);
			
				// Add this building to the lists.
				_totalBuildings.push(building);
				
				/*
				 * Deal with the placement of building buttons, may need to
				 * reset the x coordinates if they overflow.
				 */
				_buildButtonX += building.width + BUILDING_BUTTON_OFFSET;
				if (_buildButtonX > 200)
				{
					_buildButtonX = 0;
					_buildButtonY += building.y + building.height;
				}
			}
		}
		
		/**
		 * Function to close this menu, it will clear out the event listeners associated
		 * with the building buttons.
		 */
		public function closeMenu():void
		{
			for each (var button:GCBuildingButton in _totalBuildings)
			{
				button.removeEventListener(MouseEvent.CLICK, onButtonClicked);
				_buildingsArea.removeChild(button);
			}
			
			if (_buildButton.parent != null)
			{
				this.removeChild(_buildButton);
			}
		}
		
		//----------------------------------------------------------------------
		//	EVENT HANDLERS
		//----------------------------------------------------------------------
		
		private function onButtonClicked(event:MouseEvent):void
		{
			trace("GCTradePostMenu-- A building was clicked");
			// Clear out old text data
			
			
			var targetBuilding:GCBuildingButton = event.currentTarget as GCBuildingButton;
			
			/*
			 * If they clicked on the same button twice, return.
			 */
			if (_targetedBuilding != null && _targetedBuilding === targetBuilding)
			{
				return;
			}
			
			/*
			 * Clear out the old description and put a new one in.
			 */
			_descriptionText.text = "";
			_targetedBuilding = targetBuilding;
			
			/*
			 * Get the text information describing the building that
			 * was clicked and put it into the description area.
			 */
			var bldgId:uint = _targetedBuilding.getBuildingId();
			var name:String = GCBuildingData.getNameFromId(bldgId);
			var description:String = GCBuildingData.getDescriptionFromId(bldgId);
			_descriptionText.text = "Building Description\n\n" + name + "\n\n" + description;
			
			if (!_targetedBuilding.isEnabled() && 
				GCBuildingData.getBuildingTypeFromId(bldgId) == GCBuildingData.BUILDING_TYPE_HARVEST)
			{
				_descriptionText.text = _descriptionText.text + "\n\nAssign workers here to collect " + 
					GCItemData.getNameFromId(GCBuildingData.getResourceFromId(bldgId));
			}
			
			/*
			 * If the targeted building is contructable, then popup
			 * or enable the build button.
			 */
			if (_targetedBuilding.isEnabled())
			{
				if (_buildButton.parent == null)
				{
						this.addChild(_buildButton);
				}
				
				/*
				 * If the building is constructable then also display the cost
				 * to construct this building.
				 */
				while (_costText.numChildren > 1)
				{
						_costText.removeChildAt(1);
				}
				
				if (_costText.parent == null)
				{
						_descriptionArea.addChild(_costText);
				}
			
				var xPos:int = 0;
				var yPos:int = 30;
				var goldCostLabel:GCTextField = new GCTextField();
				goldCostLabel.text = "Gold Price:";
				goldCostLabel.setXY(xPos, yPos);
				goldCostLabel.setDimensions(_descriptionArea.width / 2, 20);
				var goldCostText:GCTextField = new GCTextField();
				goldCostText.text = String(GCBuildingData.getGoldCostFromId(bldgId));
				goldCostText.setXY(goldCostLabel.x + goldCostLabel.width, goldCostLabel.y);
				_costText.y = _descriptionText.y + _descriptionText.height;
				_costText.addChild(goldCostLabel);
				_costText.addChild(goldCostText);
				
				yPos += goldCostLabel.height;
				
				var costs:Dictionary = GCBuildingData.getResourceCostFromId(bldgId);
				for (var key:Object in costs)
				{
					var resourceUsedId:uint = key as uint;
					var amount:uint = costs[resourceUsedId];
					
					var resourceNameLabel:GCTextField = new GCTextField();
					resourceNameLabel.height = 20;
					resourceNameLabel.text = GCItemData.getNameFromId(resourceUsedId);
					resourceNameLabel.x = xPos;
					resourceNameLabel.y = yPos;
					var amountLabel:GCTextField = new GCTextField();
					amountLabel.height = 20;
					amountLabel.text = String(amount);
					amountLabel.x = resourceNameLabel.x + resourceNameLabel.y;
					amountLabel.y = yPos;
					
					yPos += resourceNameLabel.height;
					
					_costText.addChild(resourceNameLabel);
					_costText.addChild(amountLabel);
				}
			}
			else if (_buildButton.parent != null)
			{
					this.removeChild(_buildButton);
			}
			
			/*
			 * Check if we want to remove the text cost.
			 */
			if (!_targetedBuilding.isEnabled() && _costText.parent != null)
			{
					_descriptionArea.removeChild(_costText);
			}
		}
		
		private function onBuildClick(event:MouseEvent):void
		{
			trace("Constructed a building");
			
			/*
			 * Logically remove the building from the list of available ones
			 * to build. As far as UI goes, doing so will do something like
			 * grey out the tag or put a label that it is already constructed.
			 */
			
			 var newBuildingId:uint = _targetedBuilding.getBuildingId();
			/*
			 * Subtract the cost of the building from their account of gold and
			 * remove the buy button, do not want them to construct a building
			 * they had just successfully built. We will also need to create a new
			 * GCCityBuildingObject and place it into the city.
			 */
			var goldCost:uint = GCCityBuilding.getGoldCost(newBuildingId);
			var resourceCost:Dictionary = GCCityBuilding.getResourceCost(newBuildingId);
			
			/*
			 * Make sure they have enough gold.
			 */
			if (goldCost > GCPlayState.getPlayerGold())
			{
				GCPlayState.disableScreen(new GCTextPopup("You do not have enough gold to construct this building.", GCPlayState.enableScreen));
				return;
			}
			
			/*
			 * Look through each resource as check that they have enough resources stored
			 * in either their ship or inside their city warehouse to pay
			 */
			var amountRemoveShip:Dictionary = new Dictionary();
			var amountRemoveCity:Dictionary = new Dictionary();
			var cityInventory:GCInventory =  GCPlayState.getCurrentCity()._warehouse;
			var shipInventory:GCInventory = GCPlayState.getPlayerInventory();
			var obj:Object;
			var id:uint;
			for (obj in resourceCost)
			{
				id = obj as uint;
				var amount:uint = resourceCost[id];
				var amountPossessed:uint = 0;
				
				var item:GCItem = shipInventory.getItemFromId(id);
				amountRemoveShip[id] = 0;
				if (item != null)
				{
					if (item.quantity < amount)
					{
						amountRemoveShip[id] = item.quantity;
					}
					else
					{
						amountRemoveShip[id] = amount;
					}
					amountPossessed += item.quantity;
				}
				
				amountRemoveCity[id] = 0;
				if (cityInventory != null && amountPossessed < amount)
				{
					item = cityInventory.getItemFromId(id);
					var remaining:int = amount - amountPossessed;
					
					/*
					 * Check that there is enough in the city warehouse to
					 * cover the remaining cost
					 */
					if (item != null && item.quantity >= remaining)
					{
						amountRemoveCity[id] = remaining;
						amountPossessed += item.quantity;
					}
				}
				
				if (amountPossessed < amount)
				{
					trace("Not enough of a resource");
					GCPlayState.disableScreen(new GCTextPopup("Not enough of a resource", GCPlayState.enableScreen));
					return;
				}
			}
			
			/*
			 * At this point they have enough to continue. Remove the gold
			 * cost.
			 */
			GCPlayState.changePlayerGold( -1 * goldCost);
			
			/*
			 * Remove the resources
			 */
			for (obj in resourceCost)
			{
				id = obj as uint;
				
				if (amountRemoveShip[id] > 0)
				{
					shipInventory.removeFromInventory(id, amountRemoveShip[id]);
				}
				
				if (cityInventory != null && amountRemoveCity[id] > 0)
				{
					cityInventory.removeFromInventory(id, amountRemoveCity[id]);
				}
			}
			
			//DATABASE CALL- construct the new building
			var pid:uint = GCPlayState.playerData.getPlayerId();
			var lid:uint = GCPlayState.getCurrentCity().getId();
			if (!GCConstants.DEBUG_MODE)
			{
				GCUtil.buildStructure(pid, lid, newBuildingId, function(code:uint, data:Object):void
				{
					trace("DATABASE -- built a new structure");
					var bid:uint = data["id"];
					if (GCPlayState.tutorialSequence.currentTutorialStage >= GCTutorial.STAGE_BUILD_GATHER)
					{
						GCPlayState.increaseExperience(GCPlayState.playerData.playerLevel * 30);
					}
				});
			}
			
			 // Contructs the actual building in our logical representation
			GCPlayState.getCurrentCity().constructNewBuilding(newBuildingId);
			
			// Remove the cost description
            _descriptionArea.removeChild(_costText);
			
			_targetedBuilding.setDisabled();
			this.removeChild(_buildButton);
			
			if (GCPlayState.tutorialSequence.currentTutorialStage == GCTutorial.STAGE_BUILD_GATHER)
			{
				// Check if built first farm
				checkTutorialBuildingConstructed(GCQuestData.QUEST_TEMPLATE_TUTORIAL_12, _targetedBuilding.getBuildingId());
			}
			else if (GCPlayState.tutorialSequence.currentTutorialStage == GCTutorial.STAGE_ESTABLISH_NEW_CENTER)
			{
				// Check if built first warehouse
				checkTutorialBuildingConstructed(GCQuestData.QUEST_TEMPLATE_TUTORIAL_14, _targetedBuilding.getBuildingId());
			}
			
			if (GCBuildingData.getBuildingTypeFromId(newBuildingId) == GCBuildingData.BUILDING_TYPE_HARVEST)
			{
				_descriptionText.text = _descriptionText.text + "\n\nAssign workers here to collect " + 
					GCItemData.getNameFromId(GCBuildingData.getResourceFromId(newBuildingId));
			}
			
			if (GCConstants.LOGGING_DATA)
			{
				var o:Object = new Object();
				o["bldgId"] = newBuildingId;
				GCPlayState.logger.LogAction(new ClientAction(ClientActionType.BUILD, o));
			}
		}
		
		private function onExitPost(event:MouseEvent):void
		{
			dispatchEvent(new GCEvent(GCEvent.EXIT_MENU_EVENT));
		}
		
		//----------------------------------------------------------------------
		//	TUTORIAL FUNCTIONS
		//----------------------------------------------------------------------
		
		private function checkTutorialBuildingConstructed(template:uint, bldgId:uint):void
		{
			var quest:GCQuest = GCPlayState.tutorialSequence.getTutorialQuestFromTemplate(template);
			if (quest != null)
			{
				var goalBuildingId:uint = quest.goalId;
				
				if (goalBuildingId == bldgId)
				{
					GCPlayState.dispatchTutorialComplete(template);
				}
			}
		}
				
		//----------------------------------------------------------------------
		//	SUPER MENU FUNCTIONS
		//----------------------------------------------------------------------

		/**
		 * Method to call to refresh any dynamic parts on the menu
		 */
		public function refresh():void
		{
			
		}
		
		/**
		 * Method to enable list displays to scroll
		 */
		public function enableScrolling():void
		{
			
		}
		
		/**
		 * Method to disable list displays from scrolling
		 */
		public function disableScrolling():void
		{
			
		}
		
	}
}